class Menu:
    """A class for generating a renderable menu that modifies URL parameters."""
    def __init__(self, request, key, items, default=None, exclude=['page']):
        """Constructs a new Menu.
        request: the request object for the current view.
        key: the name of the URL parameter for this Menu.
        items: a sequence of MenuItems.
        default: the key of the MenuItem to be selected by default.
        exclude: a list of URL parameters to remove when constructing the links for each MenuItem.
        """
        self.key = key
        self.items = items
        value = request.GET.get(self.key, default)
        self.selected = value
        for item in self.items:
            item.selected = (value == item.key)
            copy = request.GET.copy()
            copy[self.key] = item.key
            for key2 in exclude:
                if key2 in copy:
                    del copy[key2]
            item.link = u'%s?%s' % (request.path, copy.urlencode())
    def as_list(self):
        """Renders the Menu as an unordered list."""
        fragments = ['<ul>']
        for item in self.items:
            fragments.append('<li>')
            fragments.append(str(item))
            fragments.append('</li>')
        fragments.append('</ul>')
        return ''.join(fragments)
    def __str__(self):
        """Renders the Menu using the default method."""
        return self.as_list()

class MenuItem:
    """A class representing an item in a Menu."""
    def __init__(self, key, label):
        """Constructs a MenuItem.
        key: the value of the Menu URL parameter when this item is selected.
        label: the name of the menu item as it will appear on the page.
        """
        self.key = key
        self.label = label
    def __str__(self):
        """Renders the MenuItem.  
        The item appears as a link only if not selected.
        """
        if self.selected:
            return u'%s' % (self.label)
        else:
            return u'<a href="%s">%s</a>' % (self.link, self.label)
        
def sample():
    """Returns a rendered sample menu.
    >>> sample()
    '<ul><li>Hot!</li><li><a href="/home/?topic=new&search=blah">New!</a></li></ul>'
    """
    from django.http import HttpRequest, QueryDict
    items = [MenuItem('hot', "Hot!"),
             MenuItem('new', "New!"), ]
    request = HttpRequest()
    request.path = '/home/'
    request.GET = QueryDict("topic=hot&search=blah&page=3")
    menu = Menu(request, 'topic', items)
    return menu.as_list()
    
if __name__ == '__main__':
    sample()